package cn.xerllent.wxtp.config;

import java.util.Map;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;

import com.google.common.collect.Maps;

import cn.hutool.core.util.ObjectUtil;
import cn.xerllent.wxtp.handler.AppAdminChangetHandler;
import cn.xerllent.wxtp.handler.AuthCancelHandler;
import cn.xerllent.wxtp.handler.AuthChangeHandler;
import cn.xerllent.wxtp.handler.AuthCreateHandler;
import cn.xerllent.wxtp.handler.BatchJobHandler;
import cn.xerllent.wxtp.handler.ContactHandler;
import cn.xerllent.wxtp.handler.EnterAgentHandler;
import cn.xerllent.wxtp.handler.ExtChatHandler;
import cn.xerllent.wxtp.handler.ExtContactHandler;
import cn.xerllent.wxtp.handler.ExtTagHandler;
import cn.xerllent.wxtp.handler.LogHandler;
import cn.xerllent.wxtp.handler.MsgHandler;
import cn.xerllent.wxtp.handler.NullHandler;
import cn.xerllent.wxtp.handler.OpenApprovalChangetHandler;
import cn.xerllent.wxtp.handler.RegisterCorpHandler;
import cn.xerllent.wxtp.handler.SchContactHandler;
import cn.xerllent.wxtp.handler.ShareAgentHandler;
import cn.xerllent.wxtp.handler.SuiteTicketHandler;
import cn.xerllent.wxtp.redis.RedisTemplateWxRedisOps;
import cn.xerllent.wxtp.utils.WxTpConsts;
import lombok.val;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.redis.WxRedisOps;
import me.chanjar.weixin.cp.bean.message.WxCpTpXmlMessage;
import me.chanjar.weixin.cp.config.WxCpTpConfigStorage;
import me.chanjar.weixin.cp.config.impl.WxCpTpRedissonConfigImpl;
import me.chanjar.weixin.cp.constant.WxCpConsts;
import me.chanjar.weixin.cp.tp.message.WxCpTpMessageMatcher;
import me.chanjar.weixin.cp.tp.message.WxCpTpMessageRouter;
import me.chanjar.weixin.cp.tp.service.WxCpTpService;
import me.chanjar.weixin.cp.tp.service.impl.WxCpTpServiceImpl;

/**
 * @author
 */
@Configuration
@EnableConfigurationProperties(WxCpTpProperties.class)
public class WxCpTpConfiguration {
	private LogHandler logHandler;
	private SuiteTicketHandler suiteTicketHandler;
	private AuthCreateHandler authCreateHandler;
	private AuthChangeHandler authChangeHandler;
	private AuthCancelHandler authCancelHandler;
	private ContactHandler contactHandler;
	private SchContactHandler schContactHandler;
	private ExtContactHandler extContactHandler;
	private ExtChatHandler extChatHandler;
	private ExtTagHandler extTagHandler;
	private RegisterCorpHandler registerCorpHandler;
	private ShareAgentHandler shareAgentHandler;
	private BatchJobHandler batchJobHandler;
	private EnterAgentHandler enterAgentHandler;
	private OpenApprovalChangetHandler openApprovalChangetHandler;
	private AppAdminChangetHandler appAdminChangetHandler;
	private MsgHandler msgHandler;
	private NullHandler nullHandler;

	private static WxCpTpProperties properties;

	private WxRedisOps wxRedisOps; //微信ticket,accesstoken随时变化量，redis缓存配置工具

	private static Map<String, WxCpTpMessageRouter> routers = Maps.newHashMap();
	private static Map<String, WxCpTpService> cpTpServices = Maps.newHashMap();

	@Autowired
	public WxCpTpConfiguration(LogHandler logHandler,
			SuiteTicketHandler suiteTicketHandler,
			AuthCreateHandler authCreateHandler,
			AuthChangeHandler authChangeHandler,
			AuthCancelHandler authCancelHandler,
			ContactHandler contactHandler,
			SchContactHandler schContactHandler,
			ExtContactHandler extContactHandler,
			ExtChatHandler extChatHandler,
			ExtTagHandler extTagHandler,
			RegisterCorpHandler registerCorpHandler,
			ShareAgentHandler shareAgentHandler,
			BatchJobHandler batchJobHandler,
			EnterAgentHandler enterAgentHandler,
			OpenApprovalChangetHandler openApprovalChangetHandler,
			AppAdminChangetHandler appAdminChangetHandler,
			MsgHandler msgHandler,
			NullHandler nullHandler,
			WxCpTpProperties properties,
			@Autowired(required = true) RedisTemplate<Object, Object> redisTemplate) {
		this.logHandler=logHandler;
		this.suiteTicketHandler=suiteTicketHandler;
		this.authCreateHandler=authCreateHandler;
		this.authChangeHandler=authChangeHandler;
		this.authCancelHandler=authCancelHandler;
		this.contactHandler=contactHandler;
		this.schContactHandler=schContactHandler;
		this.extContactHandler=extContactHandler;
		this.extChatHandler=extChatHandler;
		this.extTagHandler=extTagHandler;
		this.registerCorpHandler=registerCorpHandler;
		this.shareAgentHandler=shareAgentHandler;
		this.batchJobHandler=batchJobHandler;
		this.enterAgentHandler=enterAgentHandler;
		this.openApprovalChangetHandler=openApprovalChangetHandler;
		this.appAdminChangetHandler=appAdminChangetHandler;
		this.msgHandler=msgHandler;
		this.nullHandler=nullHandler;
		WxCpTpConfiguration.properties = properties;

		/**
		 * 为使用WxCpTpRedissonConfigImpl，实例化wxRedisOps类
		 * */
		this.wxRedisOps = new RedisTemplateWxRedisOps(redisTemplate);

	}

	public static WxCpTpProperties getProperties() {
		return properties;
	}

	public static Map<String, WxCpTpMessageRouter> getRouters() {
		return routers;
	}

	public static WxCpTpMessageRouter getRouter(String suiteName) {
		return routers.get(suiteName);
	}

	public static WxCpTpService getCpTpService(String suiteName) {
		return cpTpServices.get(suiteName);
	}

	@PostConstruct
	public void initServices() {
		properties.getSuiteConfigs().forEach(a->{
			WxCpTpConfigStorage configStorage =  WxCpTpRedissonConfigImpl.builder()
					.corpId(properties.getCorpId())
					.corpSecret(properties.getProviderSecret()) //后来加的
					.providerSecret(properties.getProviderSecret())
					.suiteId(a.getSuiteId())
					.suiteSecret(a.getSuiteSecret())
					.token(a.getSuiteToken())
					.aesKey(a.getSuiteAesKey())
					.keyPrefix("wxtp")
					.wxRedisOps(this.wxRedisOps).build();
			val service = new WxCpTpServiceImpl();
			service.setWxCpTpConfigStorage(configStorage);
			cpTpServices.put(a.getSuiteName(), service);
			routers.put(a.getSuiteName(), this.newRouter(service));
		});
	}

	private WxCpTpMessageRouter newRouter(WxCpTpService wxCpTpService) {
		final val newRouter = new WxCpTpMessageRouter(wxCpTpService);

		newRouter
		//记录所有事件的日志 （异步执行）
		.rule().handler(this.logHandler).next()

		//通知指令
		.rule().infoType(WxTpConsts.InforType.SUITE_TICKET).handler(this.suiteTicketHandler).end()
		.rule().infoType(WxTpConsts.InforType.CREATE_AUTH).handler(this.authCreateHandler).end()
		.rule().infoType(WxTpConsts.InforType.CHANGE_AUTH).handler(this.authChangeHandler).end()
		.rule().infoType(WxTpConsts.InforType.CANCEL_AUTH).handler(this.authCancelHandler).end()
		.rule().infoType(WxTpConsts.InforType.CHANGE_CONTACT).handler(this.contactHandler).end()
		.rule().infoType(WxTpConsts.InforType.CHANGE_EXTERNAL_CONTACT).handler(this.extContactHandler).end()
		.rule().infoType(WxTpConsts.InforType.CHANGE_EXTERNAL_CHAT).handler(this.extChatHandler).end()
		.rule().infoType(WxTpConsts.InforType.CHANGE_EXTERNAL_TAG).handler(this.extTagHandler).end()
		.rule().infoType(WxTpConsts.InforType.CHANGE_SCHOOL_CONTACT).handler(this.schContactHandler).end()
		.rule().infoType(WxTpConsts.InforType.REGISTER_CORP).handler(this.registerCorpHandler).end()
		.rule().infoType(WxTpConsts.InforType.SHARE_AGENT_CHANGE).handler(this.shareAgentHandler).end()
		.rule().infoType(WxTpConsts.InforType.BATCH_JOB_RESULT).handler(this.batchJobHandler).end()

		//消息
		// app管理员变更事件
		.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).event("change_app_admin").handler(this.appAdminChangetHandler).end()
		// 流程变更事件
		.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).event(WxCpConsts.EventType.OPEN_APPROVAL_CHANGE).handler(this.openApprovalChangetHandler).end()
		// 进入应用事件
		.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).event(WxCpConsts.EventType.ENTER_AGENT).handler(this.enterAgentHandler).end()
		// 点击菜单链接事件（这里使用了一个空的处理器，可以根据自己需要进行扩展
		.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).event(WxConsts.MenuButtonType.VIEW).handler(this.nullHandler).end()
		// 扫码事件（这里使用了一个空的处理器，可以根据自己需要进行扩展）
		.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).event(WxConsts.EventType.SCAN).handler(this.nullHandler).end()
		//消息处理
		.rule().async(false).matcher(new WxCpTpMessageMatcher() {
			
			@Override
			public boolean match(WxCpTpXmlMessage message) {
				if(ObjectUtil.isNotEmpty(message.getMsgType()) && !message.getMsgType().equals(WxConsts.XmlMsgType.EVENT)){
					return true;
				}
				return false;
			}
		}).handler(this.msgHandler).end()
		//默认空处理
		.rule().async(false).handler(this.nullHandler).end()
		;


		return newRouter;
	}

}
